package com.papers.juan.service.impl;

import cn.hutool.core.lang.UUID;
import com.amazonaws.util.IOUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.papers.common.constant.DictTypeConstants;
import com.papers.common.core.domain.PageQuery;
import com.papers.common.core.domain.entity.SysDictData;
import com.papers.common.core.domain.entity.SysUser;
import com.papers.common.core.page.TableDataInfo;
import com.papers.common.enums.GeneratePaperType;
import com.papers.common.enums.YesOrNo;
import com.papers.common.exception.ServiceException;
import com.papers.common.helper.LoginHelper;
import com.papers.common.utils.AesUtil;
import com.papers.common.utils.BeanCopyUtils;
import com.papers.common.utils.DateUtils;
import com.papers.common.utils.JsonUtils;
import com.papers.common.utils.StringUtils;
import com.papers.juan.domain.TJuanPaper;
import com.papers.juan.domain.TJuanPaperBakeup;
import com.papers.juan.domain.TJuanPaperBakeupDetail;
import com.papers.juan.domain.TJuanQuestion;
import com.papers.juan.domain.bean.PaperBackupJsonBean;
import com.papers.juan.domain.bean.PaperDetailBean;
import com.papers.juan.domain.bean.PaperQuestionInfoBean;
import com.papers.juan.domain.bean.PaperStatisticsBean;
import com.papers.juan.domain.bean.PaperStatisticsFieldBean;
import com.papers.juan.domain.bean.QuestionInfoBean;
import com.papers.juan.domain.bean.QuestionPropertyImportBean;
import com.papers.juan.domain.bean.QuestionTypeJsonBean;
import com.papers.juan.domain.bean.RandomTakeOutPaperBean;
import com.papers.juan.domain.dto.PaperBakeupDto;
import com.papers.juan.domain.vo.QuestionVO;
import com.papers.juan.mapper.TJuanPaperBakeupDetailMapper;
import com.papers.juan.mapper.TJuanPaperBakeupMapper;
import com.papers.juan.mapper.TJuanPaperMapper;
import com.papers.juan.mapper.TJuanQuestionMapper;
import com.papers.juan.service.ITJuanPaperBakeupService;
import com.papers.juan.utils.FileUtil;
import com.papers.system.domain.TJuanChapter;
import com.papers.system.domain.TJuanCourse;
import com.papers.system.domain.TJuanDepartment;
import com.papers.system.domain.TJuanKnowledge;
import com.papers.system.domain.TJuanMajor;
import com.papers.system.mapper.SysDictDataMapper;
import com.papers.system.mapper.SysUserMapper;
import com.papers.system.mapper.TJuanChapterMapper;
import com.papers.system.mapper.TJuanCourseMapper;
import com.papers.system.mapper.TJuanDepartmentMapper;
import com.papers.system.mapper.TJuanKnowledgeMapper;
import com.papers.system.mapper.TJuanMajorMapper;
import lombok.RequiredArgsConstructor;
import org.apache.commons.compress.utils.Lists;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ResourceUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Random;
import java.util.Set;
import java.util.TreeSet;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 试卷备份Service业务层处理
 *
 * @author libo
 * @date 2022/12/2 11:33
 */
@RequiredArgsConstructor
@Service
public class ITJuanPaperBakeupServiceImpl implements ITJuanPaperBakeupService {

    private final TJuanPaperBakeupMapper juanPaperBakeupMapper;

    private final TJuanPaperBakeupDetailMapper juanPaperBakeupDetailMapper;

    private final TJuanPaperMapper juanPaperMapper;

    private final TJuanDepartmentMapper juanDepartmentMapper;

    private final TJuanMajorMapper juanMajorMapper;

    private final TJuanCourseMapper juanCourseMapper;

    private final TJuanChapterMapper juanChapterMapper;

    private final TJuanKnowledgeMapper juanKnowledgeMapper;

    private final TJuanQuestionMapper juanQuestionMapper;

    private final SysDictDataMapper sysDictDataMapper;

    private final SysUserMapper sysUserMapper;

    /**
     * 根据id获取备份信息
     *
     * @param id id
     * @return 备份信息
     */
    @Override
    public TJuanPaperBakeup queryBakeupById(String id) {
        return juanPaperBakeupMapper.selectById(id);
    }

    /**
     * 修改试卷备份信息
     *
     * @param bakeup 试卷备份信息
     */
    @Override
    public Boolean updateBakeup(TJuanPaperBakeup bakeup) {
        bakeup.setUpdatedBy(String.valueOf(LoginHelper.getUserId()));
        bakeup.setUpdatedTime(DateUtils.getNowDate());
        return juanPaperBakeupMapper.updateById(bakeup) > 0;
    }

    /**
     * 删除试卷备份信息
     *
     * @param id 试卷备份id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteById(String id) throws FileNotFoundException {
        TJuanPaperBakeup juanPaperBakeup = juanPaperBakeupMapper.selectById(id);
        juanPaperBakeupMapper.deleteById(id);
        LambdaQueryWrapper<TJuanPaperBakeupDetail> lqw = new LambdaQueryWrapper<>();
        juanPaperBakeupDetailMapper.delete(lqw.eq(TJuanPaperBakeupDetail::getBakeupId, id));
        if (GeneratePaperType.IMPORT.getKey().equals(juanPaperBakeup.getPaperType())) {
            String paperCode = juanPaperBakeup.getNewPaperCode();
            String basePath = ResourceUtils.getURL("classpath:").getPath() + "static/papers/";
            String fileName = basePath + paperCode + ".docx";
            FileUtil.deleteFile(fileName);
        }
    }

    /**
     * 根据试卷id新增备份信息
     *
     * @param paperId 试卷id
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertByPaperId(String paperId) {
        TJuanPaper juanPaper = juanPaperMapper.selectById(paperId);
        if (ObjectUtils.isEmpty(juanPaper)) {
            throw new ServiceException("试卷不存在！");
        }
        // 题库id
        String courseId = juanPaper.getCourseId();
        // 试卷备份信息
        TJuanPaperBakeup juanPaperBakeup = new TJuanPaperBakeup();
        BeanCopyUtils.copy(juanPaper, juanPaperBakeup);
        juanPaperBakeup.setIsTakenOut(YesOrNo.NO.getKey());
        juanPaperBakeup.setPreviousPaperCode(juanPaper.getPaperCode());
        // 备份的试卷编码和名称重新生成
        juanPaperBakeup.setNewPaperCode(getNewPaperCode(courseId));
        juanPaperBakeup.setPaperName(getNewPaperName(courseId));
        juanPaperBakeup.setIsTakenOut(YesOrNo.NO.getKey());
        juanPaperBakeup.setPaperType(GeneratePaperType.MANUAL.getKey());
        juanPaperBakeup.setCreatedBy(String.valueOf(LoginHelper.getUserId()));
        juanPaperBakeup.setCreatedTime(DateUtils.getNowDate());

        TJuanCourse juanCourse = juanCourseMapper.selectById(courseId);
        if (ObjectUtils.isEmpty(juanCourse)) {
            throw new ServiceException("题库信息不存在！");
        }
        juanPaperBakeup.setCourseSubject(juanCourse.getCourseSubject());
        // 课程信息json字符串
        String courseJsonString = JsonUtils.toJsonString(juanCourse);

        // 院系信息json字符串
        String departJsonString = null;
        TJuanDepartment juanDepartment = juanDepartmentMapper.selectById(juanCourse.getDepartId());
        if (!ObjectUtils.isEmpty(juanDepartment)) {
            departJsonString = JsonUtils.toJsonString(juanDepartment);
            juanPaperBakeup.setDepartName(juanDepartment.getDepartName());
        }

        // 专业信息json字符串
        String majorJsonString = null;
        TJuanMajor juanMajor = juanMajorMapper.selectById(juanCourse.getMajorId());
        if (!ObjectUtils.isEmpty(juanMajor)) {
            majorJsonString = JsonUtils.toJsonString(juanMajor);
            juanPaperBakeup.setMajorName(juanMajor.getMajorName());
        }

        List<SysDictData> questionTypes = sysDictDataMapper.selectDictDataByType(DictTypeConstants.QUESTION_TYPE);
        if (ObjectUtils.isEmpty(questionTypes)) {
            throw new ServiceException("题型信息不存在！");
        }
        // 题型信息json字符串
        String questionTypesJsonString = JsonUtils.toJsonString(questionTypes);

        List<SysDictData> questionDifficultList = sysDictDataMapper.selectDictDataByType(DictTypeConstants.DIFFICULTY);
        if (ObjectUtils.isEmpty(questionDifficultList)) {
            throw new ServiceException("难易程度信息不存在！");
        }
        // 难易程度信息json字符串
        String difficultListJsonString = JsonUtils.toJsonString(questionDifficultList);

        List<SysDictData> capabilityLevels = sysDictDataMapper.selectDictDataByType(DictTypeConstants.CAPABILITY_LEVEL);
        if (ObjectUtils.isEmpty(capabilityLevels)) {
            throw new ServiceException("能力层次信息不存在！");
        }
        // 能力层次信息json字符串
        String capableLevelJsonString = JsonUtils.toJsonString(capabilityLevels);

        List<SysDictData> importanceList = sysDictDataMapper.selectDictDataByType(DictTypeConstants.GRADE);
        if (ObjectUtils.isEmpty(importanceList)) {
            throw new ServiceException("重要性信息不存在！");
        }
        // 重要性信息json字符串
        String importanceJsonString = JsonUtils.toJsonString(importanceList);

        String paperQuestionInfo = juanPaper.getPaperQuestionInfo();
        List<PaperQuestionInfoBean> questionInfoBeans = getQuestions(paperQuestionInfo);
        List<String> questionIds = questionInfoBeans.stream().map(PaperQuestionInfoBean::getQuestionId).collect(Collectors.toList());
        List<TJuanQuestion> questions = juanQuestionMapper.selectBatchIds(questionIds);
        // 题目列表json字符串
        String questionsJsonString = JsonUtils.toJsonString(questions);
        List<String> chapterIds = questions.stream().map(TJuanQuestion::getChapterId).distinct().collect(Collectors.toList());
        List<TJuanChapter> chapters = juanChapterMapper.selectBatchIds(chapterIds);
        // 章节列表json字符串
        String chaptersJsonString = JsonUtils.toJsonString(chapters);
        List<String> knowledgeIds = questions.stream().map(TJuanQuestion::getKnowledgeId).distinct().collect(Collectors.toList());
        List<TJuanKnowledge> knowledgeList = juanKnowledgeMapper.selectBatchIds(knowledgeIds);
        // 知识点列表json字符串
        String knowledgesJsonString = JsonUtils.toJsonString(knowledgeList);

        // 新增试卷备份信息
        juanPaperBakeupMapper.insert(juanPaperBakeup);

        // 试卷备份详情
        TJuanPaperBakeupDetail juanPaperBakeupDetail = new TJuanPaperBakeupDetail();
        juanPaperBakeupDetail.setBakeupId(juanPaperBakeup.getId());
        juanPaperBakeupDetail.setDepartInfo(departJsonString);
        juanPaperBakeupDetail.setMajorInfo(majorJsonString);
        juanPaperBakeupDetail.setCourseInfo(courseJsonString);
        juanPaperBakeupDetail.setChapterInfo(chaptersJsonString);
        juanPaperBakeupDetail.setKnowledgeInfo(knowledgesJsonString);
        juanPaperBakeupDetail.setQuestionTypeInfo(questionTypesJsonString);
        juanPaperBakeupDetail.setQuestionEasyInfo(difficultListJsonString);
        juanPaperBakeupDetail.setQuestionCapabilityLevelInfo(capableLevelJsonString);
        juanPaperBakeupDetail.setQuestionImportanceInfo(importanceJsonString);
        juanPaperBakeupDetail.setQuestionInfo(questionsJsonString);
        juanPaperBakeupDetail.setCourseInfo(courseJsonString);
        juanPaperBakeupDetail.setCreatedBy(String.valueOf(LoginHelper.getUserId()));
        juanPaperBakeupDetail.setCreatedTime(DateUtils.getNowDate());
        juanPaperBakeupDetailMapper.insert(juanPaperBakeupDetail);
    }

    /**
     * 获取卷库卷编码
     *
     * @param courseId 题库id
     * @return 试卷编码
     */
    private String getNewPaperCode(String courseId) {
        // 题库信息
        TJuanCourse juanCourse = juanCourseMapper.selectById(courseId);
        if (null == juanCourse) {
            throw new ServiceException("题库不存在！");
        }
        // 题库编码
        String courseCode = juanCourse.getCourseCode();
        LambdaQueryWrapper<TJuanPaperBakeup> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(courseId), TJuanPaperBakeup::getCourseId, courseId);
        lqw.ne(TJuanPaperBakeup::getPaperType, GeneratePaperType.IMPORT.getKey());
        lqw.orderByDesc(TJuanPaperBakeup::getCreatedTime);
        List<TJuanPaperBakeup> paperBakeups = juanPaperBakeupMapper.selectList(lqw);
        if (CollectionUtils.isEmpty(paperBakeups)) {
            return courseCode + "001";
        }
        // 最新的一份备份试卷
        TJuanPaperBakeup newestPaper = paperBakeups.get(0);
        // 最新备份试卷的试卷编码
        String newestPaperCode = newestPaper.getNewPaperCode();
        int index = Integer.parseInt(newestPaperCode.substring(newestPaperCode.length() - 3));
        return courseCode + String.format("%03d", index + 1);
    }

    /**
     * 获取试卷名称
     *
     * @param courseId 题库id
     * @return 试卷名称
     */
    private String getNewPaperName(String courseId) {
        // 题库信息
        TJuanCourse juanCourse = juanCourseMapper.selectById(courseId);
        if (null == juanCourse) {
            throw new ServiceException("题库不存在！");
        }
        // 题库名称
        String courseSubject = juanCourse.getCourseSubject();
        LambdaQueryWrapper<TJuanPaperBakeup> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(courseId), TJuanPaperBakeup::getCourseId, courseId);
        lqw.ne(TJuanPaperBakeup::getPaperType, GeneratePaperType.IMPORT.getKey());
        lqw.orderByDesc(TJuanPaperBakeup::getCreatedTime);
        List<TJuanPaperBakeup> paperBakeups = juanPaperBakeupMapper.selectList(lqw);
        String paperName;
        if (CollectionUtils.isEmpty(paperBakeups)) {
            paperName = courseSubject + "001";
            return paperName;
        }
        // 最新的一份备份试卷
        TJuanPaperBakeup newestPaper = paperBakeups.get(0);
        // 最新试卷的试卷编码
        String newestPaperCode = newestPaper.getNewPaperCode();
        int index = Integer.parseInt(newestPaperCode.substring(newestPaperCode.length() - 3));
        return courseSubject + String.format("%03d", index + 1);
    }

    /**
     * 获取试卷备份列表
     *
     * @param dto       试卷备份bto
     * @param pageQuery 分页条件
     * @return 试卷备份列表
     */
    @Override
    public TableDataInfo<TJuanPaperBakeup> queryBakeupList(PaperBakeupDto dto, PageQuery pageQuery) {
        List<SysUser> sysUsers = sysUserMapper.selectList();
        Map<Long, String> userNameMap = sysUsers.stream().collect(Collectors.toMap(SysUser::getUserId, SysUser::getUserName));
        LambdaQueryWrapper<TJuanPaperBakeup> lqw = buildQueryWrapper(dto);
        Page<TJuanPaperBakeup> juanPaperBakeups = juanPaperBakeupMapper.selectPage(pageQuery.build(), lqw);
        // 特殊处理，将createdBy赋值用户名称
        juanPaperBakeups.getRecords().forEach(o -> o.setCreatedBy(userNameMap.get(Long.valueOf(o.getCreatedBy()))));
        return TableDataInfo.build(juanPaperBakeups);
    }

    /**
     * 随机抽卷
     *
     * @param bean 随机抽取试卷bean
     * @return 试卷备份列表
     */
    @Override
    public List<TJuanPaperBakeup> randomTakeOutPaper(RandomTakeOutPaperBean bean) {
        // 抽卷份数
        int number = (null == bean.getNumber()) ? 1 : bean.getNumber();
        // 课程id
        String courseId = bean.getCourseId();
        // 课程下的未被抽卷的试卷备份列表
        List<TJuanPaperBakeup> unBeenTakenOutPaperList = juanPaperBakeupMapper.selectList(new LambdaQueryWrapper<TJuanPaperBakeup>()
            .eq(TJuanPaperBakeup::getCourseId, courseId)
            .eq(TJuanPaperBakeup::getIsTakenOut, YesOrNo.NO.getKey()));
        if (CollectionUtils.isEmpty(unBeenTakenOutPaperList)) {
            throw new ServiceException("当前卷库已被抽取完！");
        }
        if (number > unBeenTakenOutPaperList.size()) {
            throw new ServiceException("抽取的试卷份数过大！");
        }
        Set<String> existPaperIds = new TreeSet<>();
        List<TJuanPaperBakeup> randomPapers = Lists.newArrayList();
        while (existPaperIds.size() < number) {
            Random random = new Random();
            // 随机抽卷
            TJuanPaperBakeup randomPaper = unBeenTakenOutPaperList.get(random.nextInt(unBeenTakenOutPaperList.size()));
            if (!existPaperIds.contains(randomPaper.getPaperId())) {
                randomPapers.add(randomPaper);
                existPaperIds.add(randomPaper.getPaperId());
            }
        }
        // 批量修改备份试卷是否被抽取状态
        updatePaperIsTakenOutBatch(randomPapers, YesOrNo.YES);
        // 新增试卷维护记录
//        insertPaperRecordBatch(PaperRecordType.TAKE_OUT, randomPapers);
        return randomPapers;
    }

    private LambdaQueryWrapper<TJuanPaperBakeup> buildQueryWrapper(PaperBakeupDto dto) {
        LambdaQueryWrapper<TJuanPaperBakeup> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(dto.getPaperId()), TJuanPaperBakeup::getPaperId, dto.getPaperId());
        lqw.eq(StringUtils.isNotBlank(dto.getCourseId()), TJuanPaperBakeup::getCourseId, dto.getCourseId());
        lqw.like(StringUtils.isNotBlank(dto.getPaperCode()), TJuanPaperBakeup::getNewPaperCode, dto.getPaperCode());
        lqw.like(StringUtils.isNotBlank(dto.getPaperName()), TJuanPaperBakeup::getPaperName, dto.getPaperName());
        lqw.like(StringUtils.isNotBlank(dto.getDepartName()), TJuanPaperBakeup::getDepartName, dto.getDepartName());
        lqw.like(StringUtils.isNotBlank(dto.getMajorName()), TJuanPaperBakeup::getMajorName, dto.getMajorName());
        lqw.like(StringUtils.isNotBlank(dto.getCourseSubject()), TJuanPaperBakeup::getCourseSubject, dto.getCourseSubject());
        lqw.eq(StringUtils.isNotBlank(dto.getIsTakenOut()), TJuanPaperBakeup::getIsTakenOut, dto.getIsTakenOut());
        return lqw;
    }

    /**
     * 批量修改试卷是否被抽取状态
     *
     * @param juanPaperBakeups 试卷备份列表
     * @param yesOrNo          是或否枚举
     */
    private void updatePaperIsTakenOutBatch(List<TJuanPaperBakeup> juanPaperBakeups, YesOrNo yesOrNo) {
        juanPaperBakeups.forEach(item -> {
            item.setIsTakenOut(yesOrNo.getKey());
            item.setTakenOutTime(DateUtils.getNowDate());
        });
        juanPaperBakeupMapper.updateBatchById(juanPaperBakeups);
    }

    /**
     * 根据id获取题目列表
     *
     * @param id 备份id
     * @return 题目列表
     */
    @Override
    public List<TJuanQuestion> queryQuestionsById(String id) {
        TJuanPaperBakeup juanPaperBakeup = juanPaperBakeupMapper.selectById(id);
        String paperQuestionInfo = juanPaperBakeup.getPaperQuestionInfo();
        List<PaperQuestionInfoBean> questionInfoBeans = getQuestions(paperQuestionInfo);
        LambdaQueryWrapper<TJuanPaperBakeupDetail> lqw = new LambdaQueryWrapper<TJuanPaperBakeupDetail>()
            .eq(StringUtils.isNotBlank(juanPaperBakeup.getId()), TJuanPaperBakeupDetail::getBakeupId, juanPaperBakeup.getId());
        TJuanPaperBakeupDetail bakeupDetail = juanPaperBakeupDetailMapper.selectOne(lqw);
        String questionInfo = bakeupDetail.getQuestionInfo();
        List<TJuanQuestion> juanQuestions = JsonUtils.parseArray(questionInfo, TJuanQuestion.class);
        // key：题目id，value：题目信息
        Map<String, TJuanQuestion> questionMap = juanQuestions.stream().collect(Collectors.toMap(TJuanQuestion::getQuestionId, Function.identity()));
        List<TJuanQuestion> questions = Lists.newArrayList();
        questionInfoBeans.forEach(item -> questions.add(questionMap.get(item.getQuestionId())));
        return questions;
    }

    /**
     * 根据id获取试卷统计数据
     *
     * @param id 备份id
     * @return 试卷统计数据
     */
    @Override
    public PaperStatisticsBean queryPaperStatisticsById(String id) {
        TJuanPaperBakeup juanPaperBakeup = juanPaperBakeupMapper.selectById(id);
        PaperStatisticsBean bean = new PaperStatisticsBean();
        // 试卷总分
        Integer totalScore = juanPaperBakeup.getPaperTotalScore();
        // 试卷名称
        bean.setName(juanPaperBakeup.getPaperName());
        // 难度系数
        bean.setPaperEasy(juanPaperBakeup.getPaperEasy());
        String paperQuestionInfo = juanPaperBakeup.getPaperQuestionInfo();
        List<PaperQuestionInfoBean> questionInfoBeans = getQuestions(paperQuestionInfo);
        // 题目分数map
        Map<String, Integer> questionScoreMap = questionInfoBeans.stream().collect(Collectors.toMap(PaperQuestionInfoBean::getQuestionId, PaperQuestionInfoBean::getScore));
        // 试卷总题目数量
        bean.setCount(questionInfoBeans.size());
        // 试卷总分
        bean.setScore(totalScore);
        // 题目列表
        LambdaQueryWrapper<TJuanPaperBakeupDetail> lqw = new LambdaQueryWrapper<TJuanPaperBakeupDetail>()
            .eq(StringUtils.isNotBlank(juanPaperBakeup.getId()), TJuanPaperBakeupDetail::getBakeupId, juanPaperBakeup.getId());
        TJuanPaperBakeupDetail bakeupDetail = juanPaperBakeupDetailMapper.selectOne(lqw);
        String questionInfo = bakeupDetail.getQuestionInfo();
        List<TJuanQuestion> questions = JsonUtils.parseArray(questionInfo, TJuanQuestion.class);
        questions.forEach(item -> item.setScore(questionScoreMap.get(item.getQuestionId())));
        // 章节map,key：章节id，value：题目数量
        Map<String, Long> chapterMap = questions.stream().collect(Collectors.groupingBy(TJuanQuestion::getChapterId, Collectors.counting()));
        // 知识点map,key：知识点id，value：题目数量
        Map<String, Long> knowledgeMap = questions.stream().collect(Collectors.groupingBy(TJuanQuestion::getKnowledgeId, Collectors.counting()));
        // 题目类型map,key：题目类型，value：题目数量
        Map<String, Long> questionTypeMap = questions.stream().collect(Collectors.groupingBy(TJuanQuestion::getQuestionType, Collectors.counting()));
        // 难易程度map,key：难易程度，value：题目数量
        Map<String, Long> questionDifficultMap = questions.stream().collect(Collectors.groupingBy(TJuanQuestion::getQuestionEasy, Collectors.counting()));
        // 能力层次map,key：能力层次，value：题目数量
        Map<String, Long> questionCapableMap = questions.stream().collect(Collectors.groupingBy(TJuanQuestion::getCapabilityLevel, Collectors.counting()));
        // 重要性map,key：重要性，value：题目数量
        Map<String, Long> questionImportanceMap = questions.stream().collect(Collectors.groupingBy(TJuanQuestion::getQuestionGrade, Collectors.counting()));

        // 章节统计
        List<PaperStatisticsFieldBean> chapters = Lists.newArrayList();
        List<TJuanChapter> juanChapters = JsonUtils.parseArray(bakeupDetail.getChapterInfo(), TJuanChapter.class);
        for (TJuanChapter juanChapter : juanChapters) {
            PaperStatisticsFieldBean chapterFieldStatisticsBean = new PaperStatisticsFieldBean();
            chapterFieldStatisticsBean.setValue(juanChapter.getChapterId());
            chapterFieldStatisticsBean.setLabel(juanChapter.getChapterName());
            chapterFieldStatisticsBean.setCount(Math.toIntExact(chapterMap.get(juanChapter.getChapterId())));
            long score = questions.stream().filter(item -> juanChapter.getChapterId().equals(item.getChapterId())).mapToInt(TJuanQuestion::getScore).sum();
            chapterFieldStatisticsBean.setScore((int) score);
            chapterFieldStatisticsBean.setCountRate((float) chapterFieldStatisticsBean.getCount() / (float) bean.getCount());
            chapterFieldStatisticsBean.setScoreRate((float) score / (float) totalScore);
            chapters.add(chapterFieldStatisticsBean);
        }
        bean.setChapters(chapters);

        // 知识点统计
        List<PaperStatisticsFieldBean> knowledgeList = Lists.newArrayList();
        List<TJuanKnowledge> juanKnowledgeList = JsonUtils.parseArray(bakeupDetail.getKnowledgeInfo(), TJuanKnowledge.class);
        for (TJuanKnowledge juanKnowledge : juanKnowledgeList) {
            PaperStatisticsFieldBean knowledgeFieldStatisticsBean = new PaperStatisticsFieldBean();
            knowledgeFieldStatisticsBean.setValue(juanKnowledge.getKnowledgeId());
            knowledgeFieldStatisticsBean.setLabel(juanKnowledge.getKnowledgeName());
            knowledgeFieldStatisticsBean.setCount(Math.toIntExact(knowledgeMap.get(juanKnowledge.getKnowledgeId())));
            long score = questions.stream().filter(item -> juanKnowledge.getKnowledgeId().equals(item.getKnowledgeId())).mapToInt(TJuanQuestion::getScore).sum();
            knowledgeFieldStatisticsBean.setScore((int) score);
            knowledgeFieldStatisticsBean.setCountRate((float) knowledgeFieldStatisticsBean.getCount() / (float) bean.getCount());
            knowledgeFieldStatisticsBean.setScoreRate((float) score / (float) totalScore);
            knowledgeList.add(knowledgeFieldStatisticsBean);
        }
        bean.setKnowledgeList(knowledgeList);

        // 题目类型统计
        List<PaperStatisticsFieldBean> questionTypes = Lists.newArrayList();
        // 题目类型列表
        List<SysDictData> questionTypeDictDataList = JsonUtils.parseArray(bakeupDetail.getQuestionTypeInfo(), SysDictData.class);
        for (SysDictData data : questionTypeDictDataList) {
            PaperStatisticsFieldBean typeFieldStatisticsBean = new PaperStatisticsFieldBean();
            typeFieldStatisticsBean.setValue(data.getDictValue());
            typeFieldStatisticsBean.setLabel(data.getDictLabel());
            typeFieldStatisticsBean.setCount(null == questionTypeMap.get(data.getDictValue()) ?
                0 : Math.toIntExact(questionTypeMap.get(data.getDictValue())));
            if (0 == typeFieldStatisticsBean.getCount()) {
                continue;
            }
            long score = questions.stream().filter(item -> data.getDictValue().equals(item.getQuestionType())).mapToInt(TJuanQuestion::getScore).sum();
            typeFieldStatisticsBean.setScore((int) score);
            typeFieldStatisticsBean.setCountRate((float) typeFieldStatisticsBean.getCount() / (float) bean.getCount());
            typeFieldStatisticsBean.setScoreRate((float) score / (float) totalScore);
            questionTypes.add(typeFieldStatisticsBean);
        }
        bean.setQuestionTypes(questionTypes);

        // 难易程度统计
        List<PaperStatisticsFieldBean> questionDifficultList = Lists.newArrayList();
        // 难易程度列表
        List<SysDictData> difficultDictDataList = JsonUtils.parseArray(bakeupDetail.getQuestionEasyInfo(), SysDictData.class);
        for (SysDictData data : difficultDictDataList) {
            PaperStatisticsFieldBean difficultFieldStatisticsBean = new PaperStatisticsFieldBean();
            difficultFieldStatisticsBean.setValue(data.getDictValue());
            difficultFieldStatisticsBean.setLabel(data.getDictLabel());
            difficultFieldStatisticsBean.setCount(null == questionDifficultMap.get(data.getDictValue()) ?
                0 : Math.toIntExact(questionDifficultMap.get(data.getDictValue())));
            if (0 == difficultFieldStatisticsBean.getCount()) {
                continue;
            }
            long score = questions.stream().filter(item -> data.getDictValue().equals(item.getQuestionEasy())).mapToInt(TJuanQuestion::getScore).sum();
            difficultFieldStatisticsBean.setScore((int) score);
            difficultFieldStatisticsBean.setCountRate((float) difficultFieldStatisticsBean.getCount() / (float) bean.getCount());
            difficultFieldStatisticsBean.setScoreRate((float) score / (float) totalScore);
            questionDifficultList.add(difficultFieldStatisticsBean);
        }
        bean.setQuestionDifficultList(questionDifficultList);

        // 能力层次统计
        List<PaperStatisticsFieldBean> questionCapableList = Lists.newArrayList();
        // 能力层次列表
        List<SysDictData> capabilityLevels = JsonUtils.parseArray(bakeupDetail.getQuestionCapabilityLevelInfo(), SysDictData.class);
        for (SysDictData data : capabilityLevels) {
            PaperStatisticsFieldBean capableFieldStatisticsBean = new PaperStatisticsFieldBean();
            capableFieldStatisticsBean.setCount(null == questionCapableMap.get(data.getDictValue()) ?
                0 : Math.toIntExact(questionCapableMap.get(data.getDictValue())));
            if (0 == capableFieldStatisticsBean.getCount()) {
                continue;
            }
            capableFieldStatisticsBean.setValue(data.getDictValue());
            capableFieldStatisticsBean.setLabel(data.getDictLabel());
            long score = questions.stream().filter(item -> data.getDictValue().equals(item.getCapabilityLevel())).mapToInt(TJuanQuestion::getScore).sum();
            capableFieldStatisticsBean.setScore((int) score);
            capableFieldStatisticsBean.setCountRate((float) capableFieldStatisticsBean.getCount() / (float) bean.getCount());
            capableFieldStatisticsBean.setScoreRate((float) score / (float) totalScore);
            questionCapableList.add(capableFieldStatisticsBean);
        }
        bean.setQuestionCapableList(questionCapableList);

        // 重要性层次统计
        List<PaperStatisticsFieldBean> questionImportanceList = Lists.newArrayList();
        // 重要性列表
        List<SysDictData> importanceList = JsonUtils.parseArray(bakeupDetail.getQuestionImportanceInfo(), SysDictData.class);
        for (SysDictData data : importanceList) {
            PaperStatisticsFieldBean statisticsFieldBean = new PaperStatisticsFieldBean();
            statisticsFieldBean.setCount(null == questionImportanceMap.get(data.getDictValue()) ?
                0 : Math.toIntExact(questionImportanceMap.get(data.getDictValue())));
            if (0 == statisticsFieldBean.getCount()) {
                continue;
            }
            statisticsFieldBean.setValue(data.getDictValue());
            statisticsFieldBean.setLabel(data.getDictLabel());
            long score = questions.stream().filter(item -> data.getDictValue().equals(item.getQuestionGrade())).mapToInt(TJuanQuestion::getScore).sum();
            statisticsFieldBean.setScore((int) score);
            statisticsFieldBean.setCountRate((float) statisticsFieldBean.getCount() / (float) bean.getCount());
            statisticsFieldBean.setScoreRate((float) score / (float) totalScore);
            questionImportanceList.add(statisticsFieldBean);
        }
        bean.setQuestionImportanceList(questionImportanceList);

        // 相关性统计
        QuestionVO questionRelevance = new QuestionVO();
        List<String> questionCodes = questions.stream().map(TJuanQuestion::getQuestionCode).collect(Collectors.toList());
        List<TJuanQuestion> questionsForRelevance = questions.stream().filter(item -> null != item.getRelevance() && questionCodes.contains(item.getRelevance())).distinct().collect(Collectors.toList());
        questionRelevance.setQuestionList(questionsForRelevance);
        questionRelevance.setRate(0 == questionsForRelevance.size() ? 0 : (float) questionsForRelevance.size() / (float) bean.getCount());
        bean.setQuestionRelevance(questionRelevance);

        return bean;
    }

    /**
     * 根据试卷备份id获取试卷详情
     *
     * @param id 备份id
     * @return 试卷详情
     */
    @Override
    public PaperDetailBean queryPaperDetailById(String id) {
        // 试卷详情
        PaperDetailBean paperDetail = new PaperDetailBean();
        TJuanPaperBakeup juanPaperBakeup = juanPaperBakeupMapper.selectById(id);
        BeanCopyUtils.copy(juanPaperBakeup, paperDetail);
        paperDetail.setPaperCode(juanPaperBakeup.getNewPaperCode());
        // 构建试卷详情
        buildJuanPaper(paperDetail, id);

        return paperDetail;
    }

    /**
     * 导出试卷备份json信息
     *
     * @param id       备份id
     * @param response 响应
     */
    @Override
    public void exportPaperBackupJson(String id, HttpServletResponse response) {
        TJuanPaperBakeup juanPaperBakeup = juanPaperBakeupMapper.selectById(id);
        TJuanPaperBakeupDetail paperBakeupDetail = juanPaperBakeupDetailMapper.selectOne(new LambdaQueryWrapper<TJuanPaperBakeupDetail>()
            .eq(TJuanPaperBakeupDetail::getBakeupId, juanPaperBakeup.getId()));
        PaperBackupJsonBean backupJsonBean = new PaperBackupJsonBean();
        backupJsonBean.setJuanPaperBakeup(juanPaperBakeup);
        backupJsonBean.setJuanPaperBakeupDetail(paperBakeupDetail);
        String json = JsonUtils.toJsonString(backupJsonBean);
        response.setContentType("application/octet-stream");
        response.setHeader("Content-disposition", "attachment;filename=juanPaperBackup.json");
        try {
            response.getOutputStream().write(AesUtil.aesEncrypt(json).getBytes());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 导入试卷备份json信息
     *
     * @param file 试卷备份json文件
     */
    @Override
    public void importPaperBackupJson(MultipartFile file) {
        try {
            InputStream inputStream = file.getInputStream();
            String string = IOUtils.toString(inputStream);
            PaperBackupJsonBean backupJsonBean = JsonUtils.parseObject(AesUtil.aesDecrypt(string), PaperBackupJsonBean.class);
            TJuanPaperBakeup paperBakeup = backupJsonBean.getJuanPaperBakeup();
            TJuanPaperBakeupDetail paperBakeupDetail = backupJsonBean.getJuanPaperBakeupDetail();
            if (null == paperBakeup || null == paperBakeupDetail) {
                throw new ServiceException("数据包格式错误！");
            }
            paperBakeup.setIsTakenOut(YesOrNo.NO.getKey());
            paperBakeup.setPaperType(GeneratePaperType.MANUAL.getKey());
            paperBakeup.setCreatedTime(DateUtils.getNowDate());
            // 试卷备份插入或更新
            juanPaperBakeupMapper.insertOrUpdate(paperBakeup);
            // 试卷备份详情插入或更新
            juanPaperBakeupDetailMapper.insertOrUpdate(paperBakeupDetail);
        } catch (RuntimeException | IOException e) {
            e.printStackTrace();
            throw new ServiceException("数据包格式错误！");
        }
    }

    /**
     * 导入试卷
     *
     * @param list     试题属性导入bean
     * @param courseId 试卷备份文件
     * @param wordFile 试卷文件
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void importData(List<QuestionPropertyImportBean> list, String courseId, MultipartFile wordFile) {
        String originalFilename = wordFile.getOriginalFilename();
        String fileName = originalFilename.substring(0, originalFilename.lastIndexOf("."));
        // 检查试题属性导入bean
        String paperCode = checkQuestionPropertyImportBean(list, fileName);
        // 题目列表
        List<TJuanQuestion> questions = new ArrayList<>();
        // 章节列表
        List<TJuanChapter> chapters = new ArrayList<>();
        // 知识点列表
        List<TJuanKnowledge> knowledges = new ArrayList<>();
        // 构建试卷备份详情
        buildBackupDetail(list, courseId, questions, chapters, knowledges);
        Map<String, TJuanQuestion> questionMap = questions.stream().collect(Collectors.toMap(TJuanQuestion::getQuestionId, Function.identity()));
        List<SysDictData> questionTypes = sysDictDataMapper.selectDictDataByType(DictTypeConstants.QUESTION_TYPE);
        if (ObjectUtils.isEmpty(questionTypes)) {
            throw new ServiceException("题型信息不存在！");
        }

        List<SysDictData> questionDifficultList = sysDictDataMapper.selectDictDataByType(DictTypeConstants.DIFFICULTY);
        if (ObjectUtils.isEmpty(questionDifficultList)) {
            throw new ServiceException("难易程度信息不存在！");
        }

        List<SysDictData> capabilityLevels = sysDictDataMapper.selectDictDataByType(DictTypeConstants.CAPABILITY_LEVEL);
        if (ObjectUtils.isEmpty(capabilityLevels)) {
            throw new ServiceException("能力层次信息不存在！");
        }

        List<SysDictData> importanceList = sysDictDataMapper.selectDictDataByType(DictTypeConstants.GRADE);
        if (ObjectUtils.isEmpty(importanceList)) {
            throw new ServiceException("重要性信息不存在！");
        }

        // 试卷id
        String paperId = UUID.randomUUID().toString().replaceAll("-", "");
        // 试卷总分
        int paperTotalScore = list.stream().mapToInt(QuestionPropertyImportBean::getScore).sum();
        // key：题目类型，value：题目列表
        Map<String, List<QuestionPropertyImportBean>> listMap = list.stream().collect(Collectors.groupingBy(QuestionPropertyImportBean::getQuestionType));
        List<QuestionTypeJsonBean> questionTypeJsonBeans = Lists.newArrayList();
        int i = 1;
        for (String key : listMap.keySet()) {
            List<QuestionPropertyImportBean> propertyImportBeans = listMap.get(key);
            QuestionTypeJsonBean jsonBean = new QuestionTypeJsonBean();
            jsonBean.setQuestionType(String.valueOf(i));
            jsonBean.setBigName(key);
            jsonBean.setBigDesc("（本大题共" + propertyImportBeans.size() + "小题，共"
                + propertyImportBeans.stream().mapToInt(QuestionPropertyImportBean::getScore).sum() + "分");
            List<PaperQuestionInfoBean> questionInfoBeans = Lists.newArrayList();
            for (QuestionPropertyImportBean propertyImportBean : propertyImportBeans) {
                PaperQuestionInfoBean paperQuestionInfoBean = new PaperQuestionInfoBean();
                paperQuestionInfoBean.setQuestionId(propertyImportBean.getQuestionId());
                paperQuestionInfoBean.setScore(propertyImportBean.getScore());
                paperQuestionInfoBean.setQuestionType(questionMap.get(propertyImportBean.getQuestionId()).getQuestionType());
                paperQuestionInfoBean.setQuestionEasy(questionMap.get(propertyImportBean.getQuestionId()).getQuestionEasy());
                questionInfoBeans.add(paperQuestionInfoBean);
            }
            jsonBean.setQuestions(questionInfoBeans);
            questionTypeJsonBeans.add(jsonBean);
            i++;
        }
        String paperQuestionInfo = JsonUtils.toJsonString(questionTypeJsonBeans);
        TJuanPaperBakeup juanPaperBakeup = new TJuanPaperBakeup();
        juanPaperBakeup.setPaperId(paperId);
        juanPaperBakeup.setCourseId(courseId);
        juanPaperBakeup.setNewPaperCode(paperCode);
        juanPaperBakeup.setPaperName(paperCode);
        juanPaperBakeup.setPaperType(GeneratePaperType.IMPORT.getKey());
        juanPaperBakeup.setPaperTotalScore(paperTotalScore);
        juanPaperBakeup.setPaperQuestionInfo(paperQuestionInfo);
        juanPaperBakeup.setPaperQuestionInfo(paperQuestionInfo);
        TJuanCourse juanCourse = juanCourseMapper.selectById(courseId);
        if (ObjectUtils.isEmpty(juanCourse)) {
            throw new ServiceException("题库信息不存在！");
        }
        if (!"2".equals(juanCourse.getCourseType())) {
            throw new ServiceException("当前库不属于卷库！");
        }
        juanPaperBakeup.setCourseSubject(juanCourse.getCourseSubject());

        TJuanDepartment juanDepartment = juanDepartmentMapper.selectById(juanCourse.getDepartId());
        if (!ObjectUtils.isEmpty(juanDepartment)) {
            juanPaperBakeup.setDepartName(juanDepartment.getDepartName());
        }

        TJuanMajor juanMajor = juanMajorMapper.selectById(juanCourse.getMajorId());
        if (!ObjectUtils.isEmpty(juanMajor)) {
            juanPaperBakeup.setMajorName(juanMajor.getMajorName());
        }
        juanPaperBakeup.setIsTakenOut(YesOrNo.NO.getKey());
        juanPaperBakeup.setCreatedBy(String.valueOf(LoginHelper.getUserId()));
        juanPaperBakeup.setCreatedTime(DateUtils.getNowDate());
        juanPaperBakeupMapper.insert(juanPaperBakeup);

        TJuanPaperBakeupDetail juanPaperBakeupDetail = new TJuanPaperBakeupDetail();
        juanPaperBakeupDetail.setBakeupId(juanPaperBakeup.getId());
        juanPaperBakeupDetail.setChapterInfo(JsonUtils.toJsonString(chapters));
        juanPaperBakeupDetail.setKnowledgeInfo(JsonUtils.toJsonString(knowledges));
        juanPaperBakeupDetail.setQuestionTypeInfo(JsonUtils.toJsonString(questionTypes));
        juanPaperBakeupDetail.setQuestionEasyInfo(JsonUtils.toJsonString(questionDifficultList));
        juanPaperBakeupDetail.setQuestionCapabilityLevelInfo(JsonUtils.toJsonString(capabilityLevels));
        juanPaperBakeupDetail.setQuestionImportanceInfo(JsonUtils.toJsonString(importanceList));
        juanPaperBakeupDetail.setQuestionInfo(JsonUtils.toJsonString(questions));
        juanPaperBakeupDetail.setCreatedBy(String.valueOf(LoginHelper.getUserId()));
        juanPaperBakeupDetail.setCreatedTime(DateUtils.getNowDate());
        juanPaperBakeupDetailMapper.insert(juanPaperBakeupDetail);

        try {
            String basePath = ResourceUtils.getURL("classpath:").getPath() + "static/papers/";
            FileUtil.uploadFile(wordFile.getBytes(), basePath, wordFile.getOriginalFilename());
        } catch (Exception e) {
            e.printStackTrace();
            throw new ServiceException("试卷上传失败！");
        }
    }

    /**
     * 检查试题属性导入bean
     *
     * @param list     试题属性导入bean
     * @param fileName word文件名称
     */
    private String checkQuestionPropertyImportBean(List<QuestionPropertyImportBean> list, String fileName) {
        // 试卷编码
        List<String> paperCodes = list.stream().map(QuestionPropertyImportBean::getPaperCode).distinct().filter(Objects::nonNull).collect(Collectors.toList());
        if (paperCodes.size() > 1) {
            throw new ServiceException("请添加唯一的试卷编码！");
        }
        String paperCode = paperCodes.get(0);
        if (!fileName.equals(paperCode)) {
            throw new ServiceException("请传入相匹配的试题属性表和试卷！");
        }
        // 题目类型列表
        List<String> questionTypes = list.stream().map(QuestionPropertyImportBean::getQuestionType).distinct().collect(Collectors.toList());
        List<SysDictData> questionTypesForDict = sysDictDataMapper.selectDictDataByType(DictTypeConstants.QUESTION_TYPE);
        List<String> dictLabels = questionTypesForDict.stream().map(SysDictData::getDictLabel).collect(Collectors.toList());
        for (String questionType : questionTypes) {
            if (!dictLabels.contains(questionType)) {
                throw new ServiceException("字典中没有该题目类型：" + questionType);
            }
        }
        return paperCode;
    }

    /**
     * 获取题目难易程度
     *
     * @param propertyImportBean 试题属性导入bean
     * @return 题目难易程度
     */
    private static String getQuestionEasy(QuestionPropertyImportBean propertyImportBean) {
        if (null != propertyImportBean.getEasy()) {
            return "1";
        } else if (null != propertyImportBean.getMedium()) {
            return "2";
        } else {
            return "3";
        }
    }

    /**
     * 获取题目重要性
     *
     * @param propertyImportBean 试题属性导入bean
     * @return 题目重要性
     */
    private static String getQuestionImportance(QuestionPropertyImportBean propertyImportBean) {
        if (null != propertyImportBean.getNotImportant()) {
            return "1";
        } else if (null != propertyImportBean.getImportant()) {
            return "2";
        } else {
            return "3";
        }
    }

    /**
     * 获取题目能力层次
     *
     * @param propertyImportBean 试题属性导入bean
     * @return 题目能力层次
     */
    private static String getCapabilityLevel(QuestionPropertyImportBean propertyImportBean) {
        if (null != propertyImportBean.getMemorize()) {
            return "1";
        } else if (null != propertyImportBean.getUnderstand()) {
            return "2";
        } else {
            return "3";
        }
    }

    /**
     * 构建试卷备份详情
     *
     * @param propertyImportBeans 试题属性导入bean
     * @param questions           题目列表
     */
    private void buildBackupDetail(List<QuestionPropertyImportBean> propertyImportBeans, String courseId, List<TJuanQuestion> questions,
                                   List<TJuanChapter> chapters, List<TJuanKnowledge> knowledges) {
        List<SysDictData> questionTypes = sysDictDataMapper.selectDictDataByType(DictTypeConstants.QUESTION_TYPE);
        if (ObjectUtils.isEmpty(questionTypes)) {
            throw new ServiceException("题型信息不存在！");
        }
        // 题目类型map，key：题目类型名称，vale：题目类型键值
        Map<String, String> questionTypeMap = questionTypes.stream().collect(Collectors.toMap(SysDictData::getDictLabel, SysDictData::getDictValue));
        // 章节名称列表
        List<String> chapterNames = propertyImportBeans.stream().map(QuestionPropertyImportBean::getChapterName).distinct().collect(Collectors.toList());
        // 章节map，key：章节名称，value：章节id
        Map<String, String> chapterMap = new HashMap<>();
        for (String chapterName : chapterNames) {
            String chapterId = UUID.randomUUID().toString().replaceAll("-", "");
            chapterMap.put(chapterName, chapterId);
            TJuanChapter juanChapter = new TJuanChapter();
            juanChapter.setChapterId(chapterId);
            juanChapter.setChapterName(chapterName);
            chapters.add(juanChapter);
        }
        // 知识点名称列表
        List<String> knowledgeNames = propertyImportBeans.stream().map(QuestionPropertyImportBean::getKnowledgeName).distinct().collect(Collectors.toList());
        // 知识点map，key：知识点名称，value：知识点id
        Map<String, String> knowledgeMap = new HashMap<>();
        for (String knowledgeName : knowledgeNames) {
            String knowledgeId = UUID.randomUUID().toString().replaceAll("-", "");
            knowledgeMap.put(knowledgeName, knowledgeId);
            TJuanKnowledge juanKnowledge = new TJuanKnowledge();
            juanKnowledge.setKnowledgeId(knowledgeId);
            juanKnowledge.setKnowledgeName(knowledgeName);
            knowledges.add(juanKnowledge);
        }

        for (QuestionPropertyImportBean propertyImportBean : propertyImportBeans) {
            String questionId = UUID.randomUUID().toString().replaceAll("-", "");
            propertyImportBean.setQuestionId(questionId);
            TJuanQuestion juanQuestion = new TJuanQuestion();
            juanQuestion.setQuestionId(questionId);
            juanQuestion.setCourseId(courseId);
            juanQuestion.setChapterId(chapterMap.get(propertyImportBean.getChapterName()));
            juanQuestion.setKnowledgeId(knowledgeMap.get(propertyImportBean.getKnowledgeName()));
            juanQuestion.setQuestionType(questionTypeMap.get(propertyImportBean.getQuestionType()));
            juanQuestion.setQuestionEasy(getQuestionEasy(propertyImportBean));
            juanQuestion.setQuestionGrade(getQuestionImportance(propertyImportBean));
            juanQuestion.setCapabilityLevel(getCapabilityLevel(propertyImportBean));
            juanQuestion.setScore(propertyImportBean.getScore());
            juanQuestion.setCreatedBy(String.valueOf(LoginHelper.getUserId()));
            juanQuestion.setCreatedTime(DateUtils.getNowDate());
            questions.add(juanQuestion);
        }
    }

    /**
     * 获取题目列表
     *
     * @param paperQuestionInfo 试卷题目信息json
     * @return 题目列表
     */
    private static List<PaperQuestionInfoBean> getQuestions(String paperQuestionInfo) {
        List<PaperQuestionInfoBean> questions = Lists.newArrayList();
        List<QuestionTypeJsonBean> questionTypeJsonBeans = JsonUtils.parseArray(paperQuestionInfo, QuestionTypeJsonBean.class);
        for (QuestionTypeJsonBean questionTypeJsonBean : questionTypeJsonBeans) {
            questions.addAll(questionTypeJsonBean.getQuestions());
        }
        return questions;
    }

    /**
     * 构建试卷详情
     *
     * @param paperDetail 试卷详情
     * @param bakeupId    试卷备份id
     */
    private void buildJuanPaper(PaperDetailBean paperDetail, String bakeupId) {
        LambdaQueryWrapper<TJuanPaperBakeupDetail> lqw = new LambdaQueryWrapper<>();
        TJuanPaperBakeupDetail bakeupDetail = juanPaperBakeupDetailMapper.selectOne(lqw.eq(TJuanPaperBakeupDetail::getBakeupId, bakeupId));
        // 题目类型字典数据列表
        List<SysDictData> questionTypes = JsonUtils.parseArray(bakeupDetail.getQuestionTypeInfo(), SysDictData.class);
        // 题目类型map，key：题目类型键值，vale：题目类型名称
        Map<String, String> questionTypeMap = questionTypes.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        // 难易程度字典数据列表
        List<SysDictData> questionEasyList = JsonUtils.parseArray(bakeupDetail.getQuestionEasyInfo(), SysDictData.class);
        // 难易程度map，key：难易程度键值，vale：难易程度名称
        Map<String, String> questionEasyMap = questionEasyList.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        // 能力层次字典数据列表
        List<SysDictData> capabilityLevels = JsonUtils.parseArray(bakeupDetail.getQuestionCapabilityLevelInfo(), SysDictData.class);
        // 能力层次map，key：能力层次键值，vale：能力层次名称
        Map<String, String> capabilityLevelMap = capabilityLevels.stream().collect(Collectors.toMap(SysDictData::getDictValue, SysDictData::getDictLabel));
        // 知识点列表
        List<TJuanKnowledge> juanKnowledgeList = JsonUtils.parseArray(bakeupDetail.getKnowledgeInfo(), TJuanKnowledge.class);
        // 知识点map，key：知识点id，vale：知识点名称
        Map<String, String> juanKnowledgeListMap = juanKnowledgeList.stream().collect(Collectors.toMap(TJuanKnowledge::getKnowledgeId, TJuanKnowledge::getKnowledgeName));
        // 题目列表
        List<TJuanQuestion> questions = JsonUtils.parseArray(bakeupDetail.getQuestionInfo(), TJuanQuestion.class);
        // key：题目id，value：题目信息
        Map<String, TJuanQuestion> questionMap = questions.stream().collect(Collectors.toMap(TJuanQuestion::getQuestionId, Function.identity()));
        List<PaperQuestionInfoBean> paperQuestionInfoBeans = getQuestions(paperDetail.getPaperQuestionInfo());
        List<QuestionInfoBean> list = Lists.newArrayList();
        for (PaperQuestionInfoBean infoBean : paperQuestionInfoBeans) {
            QuestionInfoBean bean = new QuestionInfoBean();
            TJuanQuestion question = questionMap.get(infoBean.getQuestionId());
            BeanCopyUtils.copy(question, bean);
            bean.setQuestionType(questionTypeMap.get(infoBean.getQuestionType()));
            bean.setQuestionEasy(questionEasyMap.get(infoBean.getQuestionEasy()));
            bean.setCapabilityLevel(capabilityLevelMap.get(question.getCapabilityLevel()));
            bean.setKnowledgeName(juanKnowledgeListMap.get(question.getKnowledgeId()));
            bean.setQuestionScore(infoBean.getScore());
            bean.setQuestionDifficult(question.getQuestionDifficult().toString());
            list.add(bean);
        }
        paperDetail.setQuestionInfoList(list);
    }

}
